home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
8614
/
8614.xpi
/
modules
/
utils
/
ScriptManager.jsm
< prev
next >
Wrap
Text File
|
2010-02-10
|
10KB
|
355 lines
// DO NOT import this into the global namespace, but instead
// import it into your own namespace wrapper
var EXPORTED_SYMBOLS = ["SCRIPT_MANAGER"];
Components.utils.import("resource://glydo/utils/prototype_xul_1_6_0_3_modified.jsm");
Components.utils.import("resource://glydo/utils/io.jsm");
Components.utils.import("resource://glydo/utils/Utils.jsm");
Components.utils.import("resource://glydo/utils/Prefs.jsm");
Components.utils.import("resource://glydo/utils/Events.jsm");
Components.utils.import("resource://glydo/ClientInfo.jsm");
var ScriptManager = Prototype.Class.create(EventSource,{
initialize: function($super) {
$super();
this.remoteResourcesVersion = 0;
this.remoteResources = {};
this.localScripts = {};
this.timedSyncCallback = Prototype.F.bind(this.syncRemoteResources,this);
this.syncTimer = null;
this.loadScripts();
var me = this;
this.fixedGlobalFunctions = {
SM_dump: function(s) { me.dump(s); },
};
},
getResource: function(name) {
return this.remoteResources[name];
},
getScript: function(name) {
return this.localScripts[name] || this.getResource("scripts/" + name + ".js");
},
loadScripts: function() {
var loaded = this.loadRemoteResourcesCache();
// Start synchronizing with the remote repository
this.syncRemoteResources();
this.fire("onResourcesUpdated");
},
loadRemoteResourcesCache: function() {
var failed = true;
try {
// Load remote resources cache
file = DirIO.get("ProfD");
file.append("glydo");
DirIO.create(file);
file.append("resources");
DirIO.create(file);
file.append("remote_resources.json");
var json = FileIO.read(file);
if (json !== false) {
var cache = Prototype.S.decodeJSON(json);
this.remoteResourcesVersion = cache.version;
this.remoteResources = cache.resources;
failed = false;
}
} catch (ex) {
if (window.Components) {
Components.utils.reportError(ex);
}
}
if (failed) {
this.remoteResourcesVersion = 0;
this.remoteResources = {};
}
return !failed;
},
saveRemoteResourcesCache: function() {
// Note that multiple simultaneous saves may corrupt
// the file. We should probably move to a model
// that is more tolerant to concurrency scenarios.
// We deal with corrupt files in the load cache
// method.
var failed = true;
var contents = Prototype.O.toJSON({
version: this.remoteResourcesVersion,
resources: this.remoteResources
});
try {
// Save remote resources cache
var file = DirIO.get("ProfD");
file.append("glydo");
DirIO.create(file);
file.append("resources");
DirIO.create(file);
file.append("remote_resources.json");
FileIO.create(file);
if (!FileIO.write(file,contents)) {
throw "Can't store remote resources cache\n";
}
failed = false;
} catch (ex) {
if (window.Components) {
Components.utils.reportError(ex);
}
}
return !failed;
},
syncRemoteResources: function() {
var params = ({
updated_since: this.remoteResourcesVersion,
clientVersion: CLIENT_INFO.version
});
if (this.syncTimer !== null) {
Utils.clearTimeout(this.syncTimer);
this.syncTimer = null;
}
this.syncTimer = Utils.setTimeout(this.timedSyncCallback,Prefs.resources_repository_sync_interval_millis);
new Prototype.Ajax.Request(
Prefs.resources_repository_url, {
method: 'get',
parameters: params,
onSuccess: Prototype.F.bind(this.onGetRemoteResourcesSuccess,this),
onFailure: Prototype.F.bind(this.onAjaxFailure,this)
});
},
onAjaxFailure: function(response) {
var reason = response ? response.responseText : "Communication problem";
if (!reason) {
reason = "Communication problem";
}
},
onGetRemoteResourcesSuccess: function(response) {
if (!response || (response.status == 0)) {
this.onAjaxFailure(response);
return;
}
// We first store the result in memory
var result = response.responseJSON;
if (result) {
var updatedResources = [];
var newVersion = result.version || 0;
for (var n in result.updates) {
if (!Prototype.S.startsWith(n,".")) {
var o = result.updates[n];
if (o === null || o === undefined) {
delete this.remoteResources[n];
} else {
this.remoteResources[n] = o;
}
updatedResources.push(n);
}
}
this.remoteResourcesVersion = newVersion;
if (updatedResources.length > 0) {
this.fire("onResourcesUpdated",updatedResources);
// We save the remote resources in the local cache
this.saveRemoteResourcesCache();
}
}
},
getSandbox: function(doc) {
return new ScriptManager.Sandbox(this,doc);
},
invoke: function(doc,name,options,callbacks,libs) {
var sandbox = this.getSandbox(doc);
sandbox.invoke(name,options,callbacks,libs);
},
dump: function(s) {
},
});
ScriptManager.Sandbox = Prototype.Class.create({
initialize: function(scriptManager,doc) {
this.scriptManager = scriptManager;
this.document = doc;
var unsafeWindow = doc.defaultView;
if (unsafeWindow.wrappedJSObject) {
unsafeWindow = unsafeWindow.wrappedJSObject;
}
this.window = new XPCNativeWrapper(unsafeWindow);
this.sandbox = Components.utils.Sandbox(this.window);
this.sandbox.window = this.window;
this.sandbox.unsafeWindow = this.window.wrappedJSObject;
this.sandbox.document = this.window.document;
this.sandbox.__proto__ = this.sandbox.window;
this.sandbox.Func = {};
this.sandbox.__callbacks = {};
//this.sandbox = new XPCSafeJSObjectWrapper(this.sandbox);
this.imports = {};
this.importEnv(doc);
},
exec: function(name) {
var code = this.scriptManager.getScript(name);
if (!code) {
throw new Error("No code for script id '" + name + "'");
}
try {
Components.utils.evalInSandbox(code,this.sandbox);
} catch (e) {
var msg = (typeof e == "string") ? e : (e.name + ": " + e.message);
msg = msg + " (while executing " + name + ")";
throw new Error(msg,name,0);
}
},
importScript: function(name) {
// If script was already dynamically imported, don't import it again. Otherwise
// we import it
var imported = this.imports[name];
if (imported && imported.type == "dynamic") {
//
return;
}
// Get code
var code = this.scriptManager.getScript(name);
if (!code) {
if (imported) {
//
return;
}
throw new Error("No code for script id '" + name + "'");
}
var escName = name.toSource();
//
try {
Components.utils.evalInSandbox("Func[" + escName + "] = function(options,callbacks){"+code+"};",this.sandbox);
} catch (e) {
var msg = (typeof e == "string") ? e : (e.name + ": " + e.message);
msg = msg + " (while importing " + name + ")";
throw new Error(msg,name,0);
}
this.imports[name] = {
type: "dynamic"
};
},
importBuiltinLibraries: function(libs) {
for (var l = 0; l < libs.length; ++l) {
this.importBuiltinLibrary(libs[l]);
}
},
importBuiltinLibrary: function(library) {
for (var name in library) {
this.importBuiltinScript(name,library[name]);
}
},
importBuiltinScript: function(name,func) {
if (this.imports[name]) {
//
return;
}
// Import function
var globName = "__SM_import_" + name.replace(/[^a-zA-Z_0-9]/g,"_");
var me = this;
this.sandbox.importFunction(function(options,callbacks) {
return func(me,options,callbacks);
},globName);
var escName = name.toSource();
//
Components.utils.evalInSandbox("Func[" + escName + "] = " + globName + ";",this.sandbox);
this.imports[name] = {
type: "builtin",
func: func
};
},
importCallbacks: function(callbacks) {
Components.utils.evalInSandbox("__callbacks = {};",this.sandbox);
if (callbacks) {
for (var p in callbacks) {
var cbname = "__SM_callback_" + p;
this.sandbox.importFunction(callbacks[p],cbname);
Components.utils.evalInSandbox("__callbacks[" + p.toSource() + "]=" + cbname + ";\n" + cbname + "=undefined;",this.sandbox);
}
}
},
importEnv: function() {
this.importFixedFunctions();
var me = this;
// The import function imports into the current sandbox
this.sandbox.importFunction(function(name) {
me.importScript(name);
},"SM_import");
this.sandbox.importFunction(function(name) {
me.exec(name);
},"SM_exec");
// var win = doc.defaultView;
// var origin = win.location.protocol + "//" + win.location.host;
// this.sandbox.importFunction(function(eventType,data) {
// var evt = doc.createEvent("MessageEvents");
// evt.initMessageEvent(eventType, true, false, data, origin,null,win);
// win.dispatchEvent(evt);
// },"SM_message");
},
importFixedFunctions: function() {
for (var p in this.scriptManager.fixedGlobalFunctions) {
this.sandbox.importFunction(this.scriptManager.fixedGlobalFunctions[p],p);
}
},
invoke: function(name,options,callbacks,libs) {
// We only allow JSON-able options to be passed into scripts, for
// security purposes
options = options || {};
var optionsJSON = Prototype.O.toJSON(options);
if (libs) {
this.importBuiltinLibraries(libs);
}
this.importScript(name);
this.importCallbacks(callbacks);
var imported = this.imports[name];
if (imported.type == "builtin") {
imported.func(this,options,callbacks);
} else {
try {
Components.utils.evalInSandbox(
"(function(){return Func[" + name.toSource() + "]((" + optionsJSON + "),__callbacks);})()",
this.sandbox);
} catch (e) {
var msg = (typeof e == "string") ? e : (e.name + ": " + e.message);
msg = msg + " (while executing " + name + ")";
throw new Error(msg,name,0);
}
}
},
});
var SCRIPT_MANAGER = new ScriptManager();